//
//  ZYUtil.swift
//  ZYUICommon
//
//  Created by Yi Zhou on 2025/1/6.
//

import Foundation
import UIKit
import Photos
import CommonCrypto

public class ZYUtil: NSObject {}

// MARK: - 字串相关
public extension ZYUtil {
    
    /// 字串真实宽高
    /// - Parameters:
    ///   - str: str description
    ///   - font: font description
    /// - Returns: description
    @MainActor
    static func stringBounds(_ str: String, _ font: UIFont) -> CGRect {
        let tempLabel = UILabel()
        tempLabel.font = font
        tempLabel.numberOfLines = 0
        tempLabel.text = str
        tempLabel.sizeToFit()
        return tempLabel.bounds
    }
    
    /// 字串真实高度
    /// - Parameters:
    ///   - str: str description
    ///   - font: font description
    ///   - width: width description
    /// - Returns: description
    @MainActor
    static func stringHeight(_ str: String, _ font: UIFont, _ width: CGFloat) -> CGFloat {
        let tempLabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
        tempLabel.font = font
        tempLabel.numberOfLines = 0
        tempLabel.text = str
        tempLabel.sizeToFit()
        return tempLabel.bounds.height
    }
    
    /// 字串真实宽度
    /// - Parameters:
    ///   - str: str description
    ///   - font: font description
    ///   - width: width description
    /// - Returns: description
    @MainActor
    static func stringWidth(_ str: String, _ font: UIFont, _ height: CGFloat) -> CGFloat {
        let tempLabel = UILabel(frame: CGRect(x: 0, y: 0, width: CGFloat.greatestFiniteMagnitude, height: height))
        tempLabel.font = font
        tempLabel.numberOfLines = 0
        tempLabel.text = str
        tempLabel.sizeToFit()
        return tempLabel.bounds.width
    }
    
    /// 字串是否为空
    /// - Parameter str: str description
    /// - Returns: description
    static func stringEmpty(_ str: String?) -> Bool {
        guard let tempStr = str else { return true }
        return tempStr.isEmpty
    }
    
    /// 字串MD5
    /// - Parameter str: str description
    /// - Returns: description
    static func stringMD5(_ str: String) -> String? {
        
        let length = Int(CC_MD5_DIGEST_LENGTH)
        let messageData = str.data(using: .utf8)
        var digestData = Data(count: length)
        
        _ = digestData.withUnsafeMutableBytes { digestBytes -> Bool? in
            messageData?.withUnsafeBytes { messageBytes -> Bool in
                if let messageBytesBaseAddress = messageBytes.baseAddress, let digestBytesBlindMemory = digestBytes.bindMemory(to: UInt8.self).baseAddress {
                    CC_MD5(messageBytesBaseAddress, CC_LONG(messageData!.count), digestBytesBlindMemory)
                }
                return true
            }
        }
        return digestData.map { String(format: "%02hhx", $0) }.joined()
    }
    
    /// json字串转字典
    /// - Parameter str: str description
    /// - Returns: description
    static func stringToDict(_ str: String) -> [String: Any]? {
        let jsonStr = str
        // Step 1: 移除多余的反斜杠
        var processedJsonString = jsonStr
        
        // 使用正则表达式来移除不必要的反斜杠，确保不会破坏转义字符（例如：\"）
        let regex = try? NSRegularExpression(pattern: "\\\\(?!([\"/bfnrt]|u[0-9a-fA-F]{4}))", options: [])
        processedJsonString = regex?.stringByReplacingMatches(in: processedJsonString, options: [], range: NSRange(location: 0, length: processedJsonString.utf16.count), withTemplate: "") ?? jsonStr
        
        // Step 2: 将处理过的字符串转换为 Data
        guard let data = processedJsonString.data(using: .utf8) else {
            debugPrint("Failed to convert string to data")
            return nil
        }
        
        // Step 3: 尝试解析 JSON 数据
        do {
            if let jsonArray = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]],
               let firstDict = jsonArray.first {
                return firstDict
            } else if let jsonDict = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
                return jsonDict
            } else {
                debugPrint("Parsed JSON is neither an array of dictionaries nor a dictionary")
                return nil
            }
        } catch let error {
            debugPrint("Failed to parse JSON: \(error.localizedDescription)")
            return nil
        }
    }
    
    /// json字串转数组
    /// - Parameter str: str description
    /// - Returns: description
    static func stringToArray(_ str: String) -> [[String: Any]]? {
        var jsonStr = str
        if jsonStr.contains("\\") {
            jsonStr = jsonStr.components(separatedBy: "\\").joined()
        }
        if let data = jsonStr.data(using: .utf8) {
            do {
                let array = try JSONSerialization.jsonObject(with: data, options: [JSONSerialization.ReadingOptions.init(rawValue: 0)]) as? [[String: Any]]
                
                return array
            } catch let error {
                debugPrint(error.localizedDescription)
            }
        }
        return nil
    }
    
    /// 截取前x个字串
    /// - Parameters:
    ///   - str: str description
    ///   - length: length description
    /// - Returns: description
    static func stringPrefix(_ str: String, _ length: Int) -> String {
        let tempStr = str
        guard tempStr.count > length else {
            return tempStr
        }
        return String(tempStr.prefix(length))
    }
    
    /// 截取后x个字串
    /// - Parameters:
    ///   - str: str description
    ///   - length: length description
    /// - Returns: description
    static func stringSuffix(_ str: String, _ length: Int) -> String {
        let tempStr = str
        guard tempStr.count > length else {
            return tempStr
        }
        return String(tempStr.suffix(length))
    }
    
    /// 截取某个范围的字符串
    /// - Parameters:
    ///   - str: str description
    ///   - start: start description
    ///   - end: end description
    /// - Returns: description
    static func stringSub(_ str: String, _ start: Int, _ end: Int) -> String? {
        guard start >= 0, end <= str.count, start < end else {
            return nil
        }
        let startIndex = str.index(str.startIndex, offsetBy: start)
        let endIndex = str.index(str.startIndex, offsetBy: end)
        return String(str[startIndex..<endIndex])
    }
    
    /// 字串转富文本
    /// - Parameters:
    ///   - str: str description
    ///   - font: font description
    ///   - color: color description
    /// - Returns: description
    static func stringToAttribute(_ str: String, _ font: UIFont, _ color: UIColor) -> NSAttributedString {
        return NSAttributedString(string: str, attributes: [
            .font: font,
            .foregroundColor: color
        ])
    }
}

// MARK: - 时间相关
public extension ZYUtil {
    
    /// 获取当前时间
    /// - Parameter formatter: formatter description
    /// - Returns: description
    static func dateForNow(_ formatter: DateFormatter) -> String {
        return formatter.string(from: Date())
    }
    
    /// 时间戳formatter
    /// - Parameters:
    ///   - timestamp: timestamp description
    ///   - formatter: formatter description
    ///   - type: type description
    /// - Returns: description
    static func dateForTimestamp(_ timestamp: Int, _ formatter: DateFormatter, _ type: ZYEnumTimestamp = .second) -> String {
        var date: Date
        switch type {
        case .millisecond:
            date = Date(timeIntervalSince1970: TimeInterval(timestamp / 1000))
        case .second:
            date = Date(timeIntervalSince1970: TimeInterval(timestamp))
        }
        return formatter.string(from: date)
    }
    
    /// 时间戳显示成xx小时xx分钟xx秒
    /// - Parameters:
    ///   - timestamp: timestamp description
    ///   - type: type description
    /// - Returns: description
    static func dateForNormalDesc(_ timestamp: Int, _ type: ZYEnumTimestamp = .second) -> String {
        let interval = Double(timestamp)
        let seconds = Int(interval.truncatingRemainder(dividingBy: 60))
        let minutes = Int((interval / 60).truncatingRemainder(dividingBy: 60))
        let hours = Int(interval / 3600)
        if hours > 0 {
            return String(format: "%d小时 %d分钟 %d秒", hours, minutes, seconds)
        } else if minutes > 0 {
            return String(format: "%d分钟 %d秒", minutes, seconds)
        } else {
            return String(format: "%d秒", seconds)
        }
    }
}

// MARK: - 图片相关
public extension ZYUtil {
    /// 颜色生成图片
    /// - Parameters:
    ///   - color: color description
    ///   - size: size description
    /// - Returns: description
    static func imageWithColor(_ color: UIColor, _ size: CGSize) -> UIImage? {
        if size.width <= 0, size.height <= 0 {
            return nil
        }
        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
        let context = UIGraphicsGetCurrentContext()
        context?.setFillColor(color.cgColor)
        context?.fill(rect)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
    
    /// 渐变色图片
    /// - Parameters:
    ///   - colors: colors description
    ///   - size: size description
    /// - Returns: description
    static func imageWithGradient(_ colors: [UIColor], _ size: CGSize) -> UIImage? {
        var gradientColors:[CGColor] = []
        gradientColors = colors.map({ (color) in
            return color.cgColor
        })
        
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        let context = UIGraphicsGetCurrentContext()
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let gradient = CGGradient.init(colorsSpace: colorSpace, colors: gradientColors as CFArray, locations: nil)
        let startPoint = CGPoint(x: 0, y: 0)
        let endPoint = CGPoint(x: size.width, y: size.height)
        context?.drawLinearGradient(gradient!, start: startPoint, end: endPoint, options: .drawsBeforeStartLocation)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
    
    /// 保存图片到相册
    /// - Parameter image: image description
    static func imageSaveAlbum(_ image: UIImage, _ complate: @escaping ((_ success: Bool) ->Void)) {
        PHPhotoLibrary.shared().performChanges({
            PHAssetChangeRequest.creationRequestForAsset(from: image)
        }) { success, error in
            if success {
                complate(true)
                debugPrint("图片成功保存到相册")
            } else if let error = error {
                complate(false)
                debugPrint("保存图片失败: \(error.localizedDescription)")
            }
        }
    }
}

// MARK: - 颜色相关
public extension ZYUtil {
    
    /// 16进制颜色
    /// - Parameters:
    ///   - hexString: hexString description
    ///   - alpha: alpha description
    /// - Returns: description
    static func colorWithHex(_ hexString: String, _ alpha: CGFloat = 1.0) -> UIColor {
        var cString = hexString.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).uppercased()
        
        if cString.hasPrefix("#") {
            cString = String(cString.dropFirst())
        }
        
        if (cString.count != 6) {
            return UIColor.red
        }
        
        // 分割字符串为 R, G, B 部分
        let rString = String(cString.prefix(2))
        let gString = String(cString[cString.index(cString.startIndex, offsetBy: 2)..<cString.index(cString.startIndex, offsetBy: 4)])
        let bString = String(cString.suffix(2))
        
        // 将十六进制字符串转换为整数
        var r: CUnsignedInt = 0, g: CUnsignedInt = 0, b: CUnsignedInt = 0
        Scanner(string: rString).scanHexInt32(&r)
        Scanner(string: gString).scanHexInt32(&g)
        Scanner(string: bString).scanHexInt32(&b)
        
        return UIColor(red: CGFloat(r) / 255.0, green: CGFloat(g) / 255.0, blue: CGFloat(b) / 255.0, alpha: alpha)
    }
    
    /// 随机色
    /// - Returns: description
    static func colorRandom() -> UIColor {
        return UIColor(red: CGFloat(arc4random_uniform(256))/255.0,
                       green: CGFloat(arc4random_uniform(256))/255.0,
                       blue: CGFloat(arc4random_uniform(256))/255.0, alpha: 1);
    }
}

// MARK: - 机型判断
public extension ZYUtil {
    
    /// iphone5/5s/SE
    static func isIPHONE5() -> Bool {
        return (zScreenHeight == 568 && zScreenWidth == 320) || (zScreenHeight == 320 && zScreenWidth == 568)
    }
    
    /// iphone6/7/8
    static func isIPHONE6() -> Bool {
        return (zScreenHeight == 667 && zScreenWidth == 375) || (zScreenHeight == 375 && zScreenWidth == 667)
    }
    
    /// iphone6p/7p/8p
    static func isIPHONE6P() -> Bool {
        return (zScreenHeight == 736 && zScreenWidth == 414) || (zScreenHeight == 414 && zScreenWidth == 736)
    }
    
    /// iPhoneX/iPhoneXs
    static func isIPHONEX() -> Bool {
        return (zScreenHeight == 812 && zScreenWidth == 375) || (zScreenHeight == 375 && zScreenWidth == 812)
    }
    
    /// iPhoneXR/iPhoneXs Max
    static func isIPHONEXS_MAX() -> Bool {
        return (zScreenHeight == 896 && zScreenWidth == 414) || (zScreenHeight == 414 && zScreenWidth == 896)
    }
    
    /// iPhone12mini
    static func isIPHONE12mini() -> Bool {
        return (zScreenWidth == 360 && zScreenHeight == 780)
    }
    
    /// iPhone12 / iPhone12pro
    static func isIPHONE12() -> Bool {
        return (zScreenWidth == 390 && zScreenHeight == 844)
    }
    
    /// iPhone12proMax
    static func isIPHONE12PROMax() -> Bool {
        return (zScreenWidth == 428 && zScreenHeight == 926)
    }
    
}
